package com.gxlu.ms.base.logger;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import com.alibaba.fastjson.JSON;

import com.gxlu.ms.base.constant.BaseConstant;
import com.gxlu.ms.base.util.StringUtil;
import com.gxlu.ms.base.util.TraceUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.LoggerFactory;

/**
 * 固定头部分: [eagleEyeId][isPersist][bizType][success][errorCode][errorMsg][业务字段]
 *
 * @author lhc
 * @date 2018/3/15
 */
@Logger(bizType = BaseConstant.BASE_LOGGER_COMMON, fields = {"userId", "feature"})
public class BaseLogger implements Serializable {

    protected static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(BaseLogger.class);

    protected boolean success = false;

    protected String errorMsg;

    protected String errorCode;

    protected String userId;

    /**
     * 是否压测
     * 1: 压测,0:正常请求
     */
    protected String persistTest = "0" ;

    /**
     * 前缀 分隔符
     */
    private String prefix = "[";

    /**
     * 后缀 分隔符
     */
    private String suffix = "]";

    public BaseLogger() {

    }

    public BaseLogger(String prefix, String suffix) {
        this.prefix = prefix;
        this.suffix = suffix;
    }

    /**
     * 附加信息
     */
    protected Map<String, Object> feature = new HashMap<>();

    public String getLogger(String bizTypeMethod) {
        StringBuilder sb = new StringBuilder();

        sb.append(prefix + TraceUtil.getTraceId() + suffix);
        // 是否压测
        sb.append(prefix + getPersistTest()+ suffix);
        sb.append(prefix + bizTypeMethod + suffix);
        sb.append(prefix + (isSuccess() ? "Y" : "N") + suffix);
        sb.append(prefix + StringUtils.defaultString(getErrorCode()) + suffix);
        sb.append(prefix + StringUtils.defaultString(getErrorMsg()) + suffix);

        Logger[] loggers = getClass().getAnnotationsByType(Logger.class);
        for (Logger logger : loggers) {
            String bizType = logger.bizType();
            if (bizType.equals(bizTypeMethod)) {
                try {
                    getLogger(sb, logger);
                } catch (Exception e) {
                    LOGGER.error("[BaseLogger][getLogger]--exception:", e);
                }
                break;
            }
        }
        return sb.toString();
    }

    protected String getLogger(StringBuilder sb, Logger logger) throws NoSuchFieldException, IllegalAccessException {
        String[] fieldsNames = logger.fields();
        for (int i = 0; i < fieldsNames.length; i++) {
            String name = fieldsNames[i];
            if (name.equals("success")
                    || name.equals("errorCode")
                    || name.equals("errorMsg")) {
                continue;
            }
            if (name.equals("userId")) {
                sb.append(prefix + getUserId() + suffix);
                continue;
            }
            if (feature != null && !feature.isEmpty()) {
                sb.append(prefix + StringUtil.toString(JSON.toJSONString(feature)) + suffix);
                continue;
            }
            Field field = getClass().getDeclaredField(name);
            field.setAccessible(true);
            if (field.getType().isAssignableFrom(Boolean.TYPE)) {
                if (false == field.getBoolean(this)) {
                    sb.append(prefix + "N" + suffix);
                } else {
                    sb.append(prefix + "Y" + suffix);
                }
            } else {
                sb.append(prefix + ObjectUtils.defaultIfNull(field.get(this), "") + suffix);
            }
        }
        return sb.toString();
    }

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public Map<String, Object> getFeature() {
        return feature;
    }

    public void addFeature(String key, Object value) {
        this.feature.put(key, value);
    }

    public String getPersistTest() {
        return persistTest;
    }

    public void setPersistTest(String persistTest) {
        this.persistTest = persistTest;
    }
}
